# -*- coding: latin-1 -*-
#
# LuckyBot4, a python IRC bot
# (c) Copyright 2008 by Lucas van Dijk
# http://www.return1.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
#
# $Id: __init__.py 75 2009-05-09 16:10:49Z luckyluke56 $
#

try:
	from xml.etree import ElementTree
except ImportError:
	try:
		from elementtree import ElementTree
	except ImportError:
		raise

import urllib2 as urllib
from luckybot.bot.plugins import Plugin
from luckybot.luckynet.protocols.irc import Format
import re
import luckybot.misc as misc
import string
import datetime

class TVGidsRipper(object):
	"""
		This class rips data from tvgids.nl
	"""

	CHANNELS = {
		'Nederland 1': ('nederland 1', 'nederland1', 'ned1', 'ned 1'),
		'Nederland 2': ('nederland 2', 'nederland2', 'ned2', 'ned 2'),
		'Nederland 3': ('nederland 3', 'nederland3', 'ned3', 'ned 3'),
		'RTL 4': ('rtl4', 'rtl 4'),
		'RTL 5': ('rtl 5', 'rtl5'),
		'SBS 6': ('sbs6', 'sbs 6'),
		'NET 5': ('net 5', 'net5'),
		'RTL 7': ('rtl 7', 'rtl7'),
		'RTL 8': ('rtl 8', 'rtl8'),
		'Veronica': ('veronica', 'jetix'),
		'Nickelodeon': ('nickelodeon',),
		'Comedy Central': ('comedy central', 'cc'),
		'KETNET/Canvas': ('ketnet', 'canvas'),
		'Eén': ('een', 'eén', '1'),
		'2BE': ('2be',),
		'VT4': ('vt4',),
		'VTM': ('vtm',),
		'BBC 1': ('bbc1', 'bbc 1'),
		'BBC 2': ('bbc2', 'bbc 2'),
		'BBC 3': ('bbc3', 'bbc 3'),
		'BBC World': ('bbcw', 'bbc world'),
		'TMF': ('tmf',),
		'MTV': ('mtv',),
		'Film1.1': ('film1', 'film1.1'),
		'Film1.2': ('film2', 'film1.2'),
		'Film1.3': ('film3', 'film1.3'),
		'CNN': ('cnn',),
		'Cartoon Network': ('cartoon network', 'cartoon', 'cn'),
		'Discovery Channel': ('discovery', 'discovery channel'),
		'National Geographic': ('ngc', 'national geographic')
	}


	def __init__(self):
		"""
			Constructor, reads and parses data from
			tvgids.nl
		"""

		self._load_programs()

	def _load_programs(self):
		# Get contents from tvgids.nl
		connection = urllib.urlopen("http://www.tvgids.nl/nustraks/allezenders/")
		self.contents = connection.read()

		# Remove images
		regexp = re.compile(r'\<img\ssrc=".+"\s\/\>')
		self.contents = regexp.sub('', self.contents)

		# Setup regular expressions
		now_exp = r"""<td\ class="channel"><a[^>]+>([^<]+)</a></td>\s+
					<td\ class="time">(\d{2}:\d{2})</td>\s+
					<td\ class="title">\s+
												<a[^>]+>(.*?)</a>"""

		next_exp = r"""<td\ class="spacer">&nbsp;</td>\s+
					<td\ class="time">(\d{2}:\d{2})</td>\s+
					<td\ class="title">\s+
												<a[^>]+>(.*?)</a>"""

		regexp_now = re.compile(now_exp, re.I | re.S | re.M | re.X)
		now = regexp_now.findall(self.contents)

		regexp_next = re.compile(next_exp, re.I | re.S | re.M | re.X)
		next = regexp_next.findall(self.contents)

		print now
		print next

		print len(now)
		print len(next)

		self.programs = {}
		for key, match in enumerate(now):
			self.programs[misc.decode_htmlentities(match[0])] = {
				'now': (match[1], misc.decode_htmlentities(match[2])),
				'next': (next[key][0], misc.decode_htmlentities(next[key][1]))
			}

	def get_channel(self, channel):
		"""
			Returns a valid channel name, based on the given one
			This channel name can be used to get the current program
			whats on air now
		"""

		channel = channel.lower()
		for channel_name, possibilities in self.CHANNELS.iteritems():
			if channel in possibilities:
				return channel_name

		return False

	def get_now_onair(self, channel):
		"""
			Gets the current program on air
		"""

		channel = self.get_channel(channel)

		if (channel == False) or (not channel in self.programs):
			raise ValueError, "Channel not found"

		return (channel, self.programs[channel]['now'])

	def get_next_onair(self, channel):
		"""
			Gets the next program on air
		"""

		channel = self.get_channel(channel)

		if (channel == False) or (not channel in self.programs):
			raise ValueError, "Channel not found"

		return (channel, self.programs[channel]['next'])

	def get_channel_programs(self, channel):
		"""
			Gets the current and next program on air
		"""

		channel = self.get_channel(channel)

		if (channel == False) or (not channel in self.programs):
			raise ValueError, "Channel not found"

		return (channel, self.programs[channel])

class FilmTotaalReader(object):
	"""
		Reads from the rss feeds which movies play today on TV
	"""

	def __init__(self):
		"""
			Constructor, does nothing special
		"""

		self.movies = []

	def _get_xml(self, url):
		"""
			Gets an Element object for the given URL

			@type url: string
			@param url: The url to fetch data from

			@rtype: elementtree.Element
			@return: An Element object
		"""

		data = urllib.urlopen(url)
		contents = data.read()

		contents = contents.replace('&', '&amp;')
		tree = ElementTree.fromstring(contents)

		if not tree:
			raise Exception, 'Could not parse XML'

		return tree

	def read_movies(self):
		"""
			Does the actual reading of the rss feed
		"""

		xml = self._get_xml('http://feeds2.feedburner.com/filmtotaal/ajvt')
		items = xml.find('channel').findall('item')

		print len(items)

		for item in items:
			self._parse_movie_data(item)

		return self.movies

	def _parse_movie_data(self, item):
		"""
			Parses all movie data from RSS item
		"""

		start_time, movie_name = item.find('title').text.split(' ', 1)

		regexp = re.compile('(\d+:\d+) - (\d+:\d+) op (.*?)\. (.*?)$')
		match = regexp.search(item.find('description').text).groups()

		start_hour, start_min = start_time.split(':')
		end_hour, end_min = match[1].split(':')

		start_time = datetime.time(int(start_hour), int(start_min))
		end_time = datetime.time(int(end_hour), int(end_min))
		today = datetime.datetime.today().date()

		start_time = datetime.datetime.combine(today, start_time)
		end_time = datetime.datetime.combine(today, end_time)

		if end_time.hour < 7:
			end_time = end_time + datetime.timedelta(days=1)

		movie = {
			'start_time': start_time,
			'end_time': end_time,
			'zender': match[2],
			'titel': movie_name,
			'beschrijving': match[3]
		}

		if end_time > datetime.datetime.today():
			self.movies.append(movie)

class TVGidsPlugin(Plugin):
	"""
		Shows current and next programs on TV
	"""

	PLUGIN_INFO = {
		'name': 'TV Gids',
		'version': '1.0',
		'description': 'Wat is er nu op TV, en wat komt er?',
		'authors': ['Lucas van Dijk'],
		'website': 'http://www.return1.net'
	}

	def initialize(self):
		self.register_command('tv', self.on_tv, help="Geeft huidige en het volgende programma op de gegeven zender", args="zender")
		self.register_command('nu', self.on_tv_now, help="Geeft het huidige programma voor een bepaalde zender", args="zender")
		self.register_command('straks', self.on_tv_next, help="Geeft wat er zometeen op een gegeven zender komt", args="zender")
		self.register_command('films', self.on_films, help="Welke films zijn er vandaag op TV?")
		self.register_command('film', self.on_film, help="Geeft meer informatie over bepaalde film (gebruik eerst 'films' commando)", args="id")

	def on_tv(self, event):
		if len(event.message.bot_args) == 0:
			event.user.send_notice("Syntax: %stv zender" % self.bot.settings.get('Bot', 'command_prefix'))
			return

		tv = TVGidsRipper()

		try:
			channel, programs = tv.get_channel_programs(event.message.bot_args)

			# Setup a template string and send it to the irc channel
			template = string.Template('${c}${b}[ ${channel} ]${b} Nu:${n} (${time1}) ${program1} ${c}Straks:${n} (${time2}) ${program2}')
			vars = {
				'c': Format.color('darkblue'),
				'b': Format.bold(),
				'n': Format.normal(),
				'channel': channel,
				'time1': programs['now'][0],
				'program1': programs['now'][1],
				'time2': programs['next'][0],
				'program2': programs['next'][1]
			}

			to_send = template.safe_substitute(vars)
			event.channel.send_pm(to_send)

		except ValueError:
			event.user.send_notice("Voor die zender konden wij niks vinden..")

	def on_tv_now(self, event):
		if len(event.message.bot_args) == 0:
			event.user.send_notice("Syntax: %snu zender" % self.bot.settings.get('Bot', 'command_prefix'))
			return

		tv = TVGidsRipper()

		try:
			channel, programs = tv.get_now_onair(event.message.bot_args)

			template = string.Template('${c}${b}[ ${channel} ]${b} Nu:${n} (${time1}) ${program1}')
			vars = {
				'c': Format.color('darkblue'),
				'b': Format.bold(),
				'n': Format.normal(),
				'channel': channel,
				'time1': programs[0],
				'program1': programs[1]
			}

			to_send = template.safe_substitute(vars)
			event.channel.send_pm(to_send)

		except ValueError:
			event.user.send_notice("Voor die zender konden wij niks vinden..")

	def on_tv_next(self, event):
		if len(event.message.bot_args) == 0:
			event.user.send_notice("Syntax: %sstraks zender" % self.bot.settings.get('Bot', 'command_prefix'))
			return

		tv = TVGidsRipper()

		try:
			channel, programs = tv.get_next_onair(event.message.bot_args)

			template = string.Template('${c}${b}[ ${channel} ]${b} Straks:${n} (${time1}) ${program1}')
			vars = {
				'c': Format.color('darkblue'),
				'b': Format.bold(),
				'n': Format.normal(),
				'channel': channel,
				'time1': programs[0],
				'program1': programs[1]
			}

			to_send = template.safe_substitute(vars)
			event.channel.send_pm(to_send)

		except ValueError:
			event.user.send_notice("Voor die zender konden wij niks vinden..")

	def on_films(self, event):
		filmtotaal = FilmTotaalReader()
		self.movies = filmtotaal.read_movies()

		to_send = "%s%s[ Films vandaag %s(%sfilm id voor details) ]%s " % (Format.color('darkblue'), Format.bold(), Format.bold(), self.bot.settings.get('Bot', 'command_prefix'), Format.normal())

		template = string.Template('(${id})${c} ${time}${n} ${title} ${n}')
		for id, movie in enumerate(self.movies):
			vars = {
				'c': Format.color('darkblue'),
				'n': Format.normal(),
				'id': id + 1,
				'time': movie['start_time'].strftime('%H:%M'),
				'title': movie['titel']
			}

			if len(to_send + template.safe_substitute(vars)) > 255:
				event.channel.send_pm(to_send)
				to_send = ""

			to_send += template.safe_substitute(vars)

		if to_send:
			event.channel.send_pm(to_send)

	def on_film(self, event):
		if not event.message.bot_args.isdigit():
			event.user.send_notice('Syntax: %sfilm id' % self.bot.settings.get('Bot', 'command_prefix'))
			return

		id = int(event.message.bot_args) - 1
		if id < 0 or id >= len(self.movies):
			event.channel.send_pm('Die film bestaat niet')
			return

		movie = self.movies[id]

		template1 = string.Template('${c}${b}${titel}${b}${n} | ${zender} |${c} ${start_time}${n} -${c} ${end_time}${n}')
		template2 = string.Template('${beschrijving}')

		movie['c'] = Format.color('darkblue')
		movie['b'] = Format.bold()
		movie['n'] = Format.normal()
		movie['start_time'] = movie['start_time'].strftime('%H:%M')
		movie['end_time'] = movie['end_time'].strftime('%H:%M')

		event.channel.send_pm(template1.safe_substitute(movie))
		event.channel.send_pm(template2.safe_substitute(movie))









